package com.rzico.sbl.ui.member

import android.Manifest
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import android.os.Bundle
import android.os.PersistableBundle
import android.provider.Settings
import android.view.inputmethod.EditorInfo
import androidx.activity.result.ActivityResultLauncher
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
import com.amap.api.convertToLatLng
import com.amap.api.convertToLatLonPoint
import com.amap.api.maps.AMap
import com.amap.api.maps.AMapException
import com.amap.api.maps.CameraUpdateFactory
import com.amap.api.maps.model.BitmapDescriptorFactory
import com.amap.api.maps.model.LatLng
import com.amap.api.maps.model.MyLocationStyle
import com.amap.api.services.core.AMapException.CODE_AMAP_SUCCESS
import com.amap.api.services.core.PoiItem
import com.amap.api.services.core.PoiItemV2
import com.amap.api.services.geocoder.GeocodeSearch
import com.amap.api.services.geocoder.RegeocodeQuery
import com.amap.api.services.help.Inputtips
import com.amap.api.services.help.InputtipsQuery
import com.amap.api.services.poisearch.PoiSearchV2
import com.amap.api.setCameraChangeListener
import com.amap.api.setPoiSearchListener
import com.fondesa.kpermissions.allGranted
import com.fondesa.kpermissions.anyPermanentlyDenied
import com.fondesa.kpermissions.extension.permissionsBuilder
import com.fondesa.kpermissions.extension.send
import com.jeremyliao.liveeventbus.LiveEventBus
import com.rzico.sbl.R
import com.rzico.sbl.databinding.ActivityMemberAdressAddBinding
import com.xinnuo.common.extend.*
import com.xinnuo.common.helper.hideSoftInput
import com.xinnuo.common.helper.startJumpAnimator
import com.xinnuo.common_ui.base.BaseActivity
import com.xinnuo.common_ui.base.addItems
import com.xinnuo.common_ui.base.loadLinear
import com.xinnuo.common_ui.utils.clear
import com.xinnuo.common_ui.utils.showHintDialog
import com.xinnuo.common.decoration.DividerLRDecoration
import com.xinnuo.slimadapter.SlimAdapter
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext

class MemberAdressAddActivity : BaseActivity(R.layout.activity_member_adress_add) {

    private val mBinding by lazy { ActivityMemberAdressAddBinding.bind(getRootView()) }

    private lateinit var mLauncher: ActivityResultLauncher<Intent>

    private lateinit var mQuery: PoiSearchV2.Query
    private lateinit var mPoiSearch: PoiSearchV2

    private lateinit var mGeoSearch: GeocodeSearch

    private var isStarted = false
    private var mCityCode = ""

    override fun initData() {
        initTitle(title = "选择位置", name = "确定")
        initLayout()
        initPoiSearch()
        initGeoSearch()
        initInputSearch()

        mLauncher = requestForResult { initAmap() }

        requestPermission()
    }

    /**
     * 定位权限申请
     */
    private fun requestPermission() {
        permissionsBuilder(
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION
        )
            .build()
            .send {
                when {
                    it.allGranted() -> initAmap()
                    it.anyPermanentlyDenied() -> showPermissionDialog()
                    else -> finishView()
                }
            }
    }

    /**
     * 权限禁止显示后提示操作
     */
    private fun showPermissionDialog() {
        showHintDialog(
            title = "提示",
            hint = "位置权限被禁止开启，请打开权限设置页面手动开启",
            sure = "去设置",
            cancel = "再想想",
            isForced = true,
            onCancel = { finishView() },
            onSure = {
                mLauncher.launch(
                    Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                        .apply {
                            data = Uri.parse("package:$packageName")
                        }
                )
            }
        )
    }

    /**
     * 地图显示初始化
     */
    private fun initAmap() {
        mBinding.adressMap.map.apply {
            uiSettings.apply {
                isZoomControlsEnabled = false     //缩放按钮，默认打开
                isCompassEnabled = false          //指南针，默认不显示
                isMyLocationButtonEnabled = false //定位按钮
                isScaleControlsEnabled = false    //比例尺
                isRotateGesturesEnabled = false   //旋转手势
                isTiltGesturesEnabled = false     //倾斜手势
                setLogoBottomMargin(-100)         //隐藏logo
            }

            isTrafficEnabled = false       //实时交通状况
            mapType = AMap.MAP_TYPE_NORMAL //矢量地图模式
            isMyLocationEnabled = true     //触发定位并显示定位层
            showIndoorMap(true)            //设置是否显示室内地图
            moveCamera(CameraUpdateFactory.zoomTo(18f)) //缩放级别

            myLocationStyle = MyLocationStyle().apply {
                // 定位一次，且将视角移动到地图中心点
                myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATE)
                strokeColor(Color.TRANSPARENT)     //设置定位蓝点精度圆圈的边框颜色
                radiusFillColor(Color.TRANSPARENT) //设置定位蓝点精度圆圈的填充颜色
                showMyLocation(true)               //设置是否显示定位小蓝点
                // 设置定位蓝点的icon图标方法
                myLocationIcon(BitmapDescriptorFactory.fromResource(R.mipmap.ic_location_point))
            }

            // 默认显示郑州经纬度
            moveCamera(
                CameraUpdateFactory.newLatLng(
                    LatLng(34.7466, 113.625367)
                )
            )

            // 设置用户定位信息监听
            setOnMyLocationChangeListener { }

            // 地图状态的监听
            setCameraChangeListener {
                onCameraChangeFinish {
                    mBinding
                        .adressCenter
                        .startJumpAnimator(100f)

                    if (isStarted) {
                        pageNum = 1
                        getData(pageNum)
                    } else isStarted = true
                }
            }
        }
    }

    /**
     * 初始化地址列表
     */
    private fun initLayout() {
        mBinding
            .adressList
            .apply {
                loadLinear(
                    onLoad = {
                        isLoadingMore
                            .conditionFalse {
                                isLoadingMore = true
                                getData(pageNum)
                            }
                    }
                )

                addItemDecoration(DividerLRDecoration(bottom = 0.5f))

                mAdapter = SlimAdapter.creator()
                    .register<PoiItemV2>(R.layout.item_map_list) { jector, bean, _ ->
                        jector.text(R.id.item_map_name, bean.title)
                            .text(R.id.item_map_hint, bean.snippet)
                            .clicked {
                                mBinding
                                    .adressMap
                                    .map
                                    .animateCamera(
                                        CameraUpdateFactory.changeLatLng(
                                            bean.latLonPoint.convertToLatLng()
                                        )
                                    )
                            }
                    }
                    .attachTo(this)
            }

        tvRight?.oneClick {
            getGeoSearchData(mBinding.adressMap.map.cameraPosition.target)
        }
    }

    /**
     * 初始化 POI检索
     */
    private fun initPoiSearch() {
        // https://lbs.amap.com/api/android-sdk/guide/map-data/poi
        // 第一个参数表示搜索关键字，未设置区域（默认为全国搜索）时，如果涉及多个城市数据返回，仅会返回建议城市。
        // 第二个参数表示POI搜索类型，选用POI搜索类型时建议填写类型代码，
        // 不设置POI的类别，默认返回“餐饮服务”、“商务住宅”、“生活服务”这三种类别的POI。多个类别以“|”拼接
        // 第三个参数表示POI搜索区域，可以是城市编码也可以是城市名称，也可以传空字符串，空字符串代表在全国范围内进行搜索。
        mQuery = PoiSearchV2.Query(
            "",
            "010000|020000|030000|050000|060000|070000|080000|090000|100000|120000|130000|140000|160000|170000",
            ""
        ).apply {
            pageSize = 20
            isDistanceSort = true
            // extensions = "all"
        }

        mPoiSearch = PoiSearchV2(this, mQuery).apply {
            setPoiSearchListener {
                onPoiSearched { result, code ->
                    dismissLoading()

                    if (code == CODE_AMAP_SUCCESS
                        && result != null
                        && result.query != null
                    ) {
                        if (pageNum == 1) {
                            mList.notEmpty {
                                mBinding
                                    .adressList
                                    .scrollToPosition(0)
                            }

                            mList.clear()
                        }

                        mList.addItems(result.pois)
                        result.pois.notEmpty { pageNum++ }
                        mAdapter.setDataList(mList)

                        if (mCityCode.isEmpty() && mList.isNotEmpty()) {
                            mCityCode = (mList[0] as PoiItemV2).cityCode
                        }

                        isLoadingMore = false

                        mBinding
                            .adressEmpty
                            .isVisible = mList.isEmpty()
                    }
                }
            }
        }
    }

    /**
     * 初始化逆地理编码
     */
    private fun initGeoSearch() {
        mGeoSearch = GeocodeSearch(this)
    }

    /**
     * 初始化输入框
     */
    private fun initInputSearch() {
        mBinding.adressEdit.apply {
            setOnEditorActionListener { _, actionId, _ ->
                if (actionId == EditorInfo.IME_ACTION_SEARCH) {
                    hideSoftInput() //隐藏软键盘

                    if (this.text.isBlank()) showToast("请输入搜索地址")
                    else getSearchData(this.textTrim)
                }
                return@setOnEditorActionListener false
            }
        }

        mBinding.adressSearch.oneClick {
            if (mBinding.adressEdit.text.isBlank()) {
                showToast("请输入搜索地址")
            } else {
                getSearchData(mBinding.adressEdit.textTrim)
            }
        }
    }

    /**
     * 获取逆地理编码结果
     */
    private fun getGeoSearchData(target: LatLng) {
        lifecycleScope.launch {
            val result = withContext(Dispatchers.IO) {
                try {
                    mGeoSearch.getFromLocation(
                        // 第一个参数表示一个Latlng，
                        // 第二参数表示范围多少米，
                        // 第三个参数表示是火系坐标系还是GPS原生坐标系
                        RegeocodeQuery(
                            target.convertToLatLonPoint(),
                            20f,
                            GeocodeSearch.AMAP
                        )
                    )
                } catch (e: AMapException) {
                    e.printStackTrace()
                    null
                }
            }

            if (result != null
                && result.formatAddress != null
            ) {
                val poiItem = PoiItem(
                    "",
                    target.convertToLatLonPoint(),
                    result.formatAddress
                        .trimStart(*result.province.toCharArray())
                        .trimStart(*result.city.toCharArray())
                        .trimStart(*result.district.toCharArray()), ""
                ).apply {
                    adCode = result.adCode
                    provinceName = result.province
                    cityName = result.city
                    adName = result.district
                }

                // 编辑地址、添加店铺
                LiveEventBus
                    .get("adressAdd")
                    .post(poiItem)

                finishView()
            } else {
                showToast("位置信息获取失败，请重新选择！")
            }
        }
    }

    /**
     * 获取关键字检索结果
     */
    private fun getSearchData(input: String) {
        Inputtips(
            this,
            InputtipsQuery(input, mCityCode)
        ).apply {
            setInputtipsListener { tips, code ->
                mBinding.adressEdit.clear()

                if (code == CODE_AMAP_SUCCESS
                    && !tips.isNullOrEmpty()
                ) {
                    val latLng = tips.firstOrNull { it.point != null }
                    latLng?.let {
                        mBinding
                            .adressMap
                            .map
                            .animateCamera(
                                CameraUpdateFactory.changeLatLng(
                                    it.point.convertToLatLng()
                                )
                            )
                    }
                } else {
                    showToast("没有找到位置，请重新输入！")
                }
            }
        }.requestInputtipsAsyn()
    }

    /**
     * 获取周边检索结果
     */
    override fun getData(index: Int, isLoading: Boolean) {
        if (index == 1) showLoading()

        mQuery.pageNum = index

        val latLng = mBinding.adressMap.map.cameraPosition.target
        mPoiSearch.bound =
            PoiSearchV2.SearchBound(
                latLng.convertToLatLonPoint(),
                500
            )
        mPoiSearch.searchPOIAsyn()
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // onCreate时执行mMapView.onCreate(savedInstanceState)，创建地图
        mBinding.adressMap.onCreate(savedInstanceState)
    }

    override fun onSaveInstanceState(outState: Bundle, outPersistentState: PersistableBundle) {
        super.onSaveInstanceState(outState, outPersistentState)
        // onSaveInstanceState时执行mMapView.onSaveInstanceState (outState)，保存地图当前的状态
        mBinding.adressMap.onSaveInstanceState(outState)
    }

    override fun onResume() {
        super.onResume()
        // onResume时执行mMapView.onResume ()，重新绘制加载地图
        mBinding.adressMap.onResume()
    }

    override fun onPause() {
        super.onPause()
        // onPause时执行mMapView.onPause ()，暂停地图的绘制
        mBinding.adressMap.onPause()
    }

    override fun onDestroy() {
        super.onDestroy()
        // onDestroy时执行mMapView.onDestroy()，销毁地图
        mBinding.adressMap.onDestroy()
    }

}